#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @author: Florian Dorn <florian.dorn@gmail.com>
# @package: agenda
# @license: GNU GPLv2
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

import gtk
import re
import pango
import locale
import gobject
import datetime


from agenda import FilterType
from agenda import ANOTHER_DAY_FMT, TIME_FMT
from agenda import get_timeout_add_time

from gettext import gettext as _

markupRe    	= re.compile( '(<u>|</u>|<i>|</i>|<b>|</b>)')
underlineRe 	= re.compile( '(<u>|</u>)')

#PROGRESS_INCICATOR = u'▂▃▄▅▆▇█'
#PROGRESS_INCICATOR = u'◔◑◕●'
#○◔◑◕●


DAY = _("day")
DAYS = _("days")
HOUR = _("h")
MINUTE = _("m")
template = '<small>%s<b>%s</b></small>'
template_past = '<small>%s%s</small>'
PointerCursor = gtk.gdk.Cursor(gtk.gdk.HAND2)
black  = gtk.gdk.color_parse('#000000')
def getDateLong(d):
	return d.strftime( "%%a, %s" % ANOTHER_DAY_FMT)
def timedelta2milli(td):
	return int((td.days * 86400000) + (td.seconds*1000) + (td.microseconds / 1000.0))

class EventWidget (gtk.VBox):
	__gtype_name__ = 'EventWidget'
	"""
	
	"""
	row_string_template = '<span %s>%s</span>' #color="%s"
	row_string_template_now = '<b>%s</b>' % row_string_template
	_event = None
	day4filter = ""
	start_time = ""

	def item_changed_callback(self,cal_event):
		#print "item_changed_callback"
		self.update_ui()
	def calendar_changed_callback(self,cal):
		self.update_ui()
	def __init__(self, event):
		gtk.VBox.__init__(self)
		
		self.event = event

		self.day4filter = event.start_time.date().strftime("%A").lower()
		try:
			self.color =	gtk.gdk.color_parse(event.get_color() )
		except:
			self.color = 	black
		self._timeout_redraw = -1
		name = gtk.Label()
		name.modify_fg(name.state,self.color)
		name.set_alignment(0,0.5)
		name.set_ellipsize(pango.ELLIPSIZE_END)
				
		time_info = gtk.Label()
		time_info.set_alignment(1,0.5)
		time_info.modify_fg(time_info.state, self.color)
		
		nameEvtBox_inner = gtk.HBox()
		nameEvtBox_inner.set_border_width(2)
		nameEvtBox_inner.set_spacing(4)
		
		
		
		time_label = None
		if(not self.event.is_all_day()):
			time_label = gtk.Label()
			time_label.modify_fg(time_label.state,self.color)
			time_label = gtk.Label()
			time_label.modify_fg(time_label.state,self.color)
			self.start_time = self.getHourMinuteMarkup(event.start_time)
			nameEvtBox_inner.pack_start(time_label,False,False)
		self.time_label = time_label

		nameEvtBox_inner.pack_start(name,True,True)
		nameEvtBox_inner.pack_start(time_info,False,False)

		nameEvtBox = gtk.EventBox()
		nameEvtBox.set_visible_window(False)
		nameEvtBox.add(nameEvtBox_inner)
		
		nameEvtBox.connect('button-press-event',self.on_click_cb)
		nameEvtBox.connect('enter-notify-event',self.on_enter_cb)
		nameEvtBox.connect('leave-notify-event',self.on_leave_cb)
		
		
		self.details = details = gtk.Alignment(.5,.5,1,1) 
		self.details.set_padding(0,0,12,0)

		self.qdet = gtk.Alignment(.5,.5,1,1) 
		self.qdet.set_padding(0,0,12,0)
		#TODO: MUST UPDATE THE QDETLABEL AS WELL
		qd = []
		if(self.event.comment):
			qd.append ("<i>%s</i>" % ( gobject.markup_escape_text(self.event.comment.strip())) )
		if(self.event.place):
			qd.append ("<i>%s: %s</i>" %(_("Where"), gobject.markup_escape_text(self.event.place.strip())))
		qd = "\n".join(qd)
		if len(qd):
			qdetlabel = gtk.Label()
			qdetlabel.set_alignment(0,0.5)
			qdetlabel.set_selectable(True)
			qdetlabel.set_line_wrap_mode(pango.WRAP_WORD_CHAR)
			qdetlabel.set_line_wrap(True)
			qdetlabel.modify_fg(qdetlabel.state,self.color)
			qdetlabel.set_markup("<small>%s</small>" % qd)
			self.qdet.add(qdetlabel)

		self.pack_start(nameEvtBox)
		self.pack_start(self.qdet)
		self.pack_start(details)
		
		details.set_no_show_all(True)
		time_info.set_no_show_all(True)
		self.show_all()
		
		self.name_label = name
		self.dtext = ""
		self.time_info = time_info
		self.nameEvtBox = nameEvtBox
		self.details_label = None
		self.update_ui()
		self.event.connect("changed",self.item_changed_callback)
		self.event.calendar.connect("changed",self.calendar_changed_callback)
	def add_detail_view(self):
		if (self.details.get_child()):
			return
		l = gtk.Label()
		l.set_alignment(0,0.5)
		l.set_selectable(True)
		l.set_line_wrap_mode(pango.WRAP_WORD_CHAR)
		l.set_line_wrap(True)
		
		l.set_markup(self.dtext)
		self.details_label = l
		l.modify_fg(l.state,black)
		self.details.add(l)
		self.details.connect("size-allocate",self.details_box_size_allocate)
		l.show()
	def update_ui(self):
		if(self._timeout_redraw != -1):
			gobject.source_remove(self._timeout_redraw)

		if self.event.is_visible():
			self.show()
		else:
			self.hide()
			return

		if(not self.event.is_today()):
			self.time_info.hide()
		else:
			self.time_info.show()
			
		if(not self.event.is_all_day()):
			ppart = ""
			t = template
			#if self.event.is_now():
			#	progress = self.event.get_progress()
			#	ppart = "%s " % PROGRESS_INCICATOR[int(progress*len(PROGRESS_INCICATOR))]
			if self.event.is_past():
				#print "%s is in the past for today" % self.event
				t = template_past
			self.time_label.set_markup(t   % (ppart,self.start_time))
		
		self.name_label.set_markup('%s' % self.get_title_string())
		self.time_info.set_markup(self.getDurationMarkup())
		#determine the next update time
		if(self.event.is_past()):
			nud = -1
		
		if(self.event.is_now()):
			nud = self.event.get_next_end()
			
			"""
			if(not self.event.is_all_day()):
				progress = self.event.get_progress()
				#print len(PROGRESS_INCICATOR)
				#print progress
				step = 1+ int(progress*len(PROGRESS_INCICATOR))
				update_interval = datetime.timedelta(seconds=self.event.get_dur_sec() / float(len(PROGRESS_INCICATOR)))
				#print "updates are every %s" % update_interval
				#print "now we are at position %s" % step
			 	nud = self.event.start_time + update_interval * step
			"""
		else:
			nud = self.event.start_time
		milli = get_timeout_add_time( nud )
		if(milli > 0):
			#print "Installing timeout for %s: %s" % (self.event,nud)
			self._timeout_redraw = gobject.timeout_add(milli+50, self.update_ui)


	
		dtext = []
		if(self.event.is_all_day()):
			if(self.event.duration.days >= 1):
				time_i = ("<small>%s</small>" % _("<i>until %s</i>") % (getDateLong(self.event.end_time)))
		else:
			time_i = ("<small><i>%s - %s</i></small>" % (self.getHourMinuteMarkup(self.event.start_time), self.getHourMinuteMarkup(self.event.end_time)))
		
		dtext.append("<b>%s</b> %s" % (gobject.markup_escape_text(self.event.title),time_i )) 
		if(self.event.place):
			dtext.append("<b>%s:</b> %s" %(_("Where"), gobject.markup_escape_text(self.event.place)))
			pass
	
		if(self.event.comment):
			dtext.append("<i>%s</i>" % ( gobject.markup_escape_text(self.event.comment)) )
			pass

		dtext.append("<b>%s:</b> <i>%s</i>" % (_("Calendar"), gobject.markup_escape_text(self.event.calendar.get_name())))
		#dtext.append("<tt>%s</tt>" % gobject.markup_escape_text(self.event.debug_info()))
		self.dtext = "\n".join(dtext)		
		if self.details_label:			
			self.details_label.set_markup(self.dtext)
		return False
	def get_title_string(self):
		rowString = ""
		markup = ""
		if(self.event.is_past()):
			markup+= 'strikethrough="true"'
		if(not self.event.is_confirmed()):
			markup+= 'font-style="italic"'
		if(self.event.is_all_day()):
			rowString = self.row_string_template % (markup, gobject.markup_escape_text(self.event.title.strip()) )
		else:
			if(self.event.is_now()):
				rowString = self.row_string_template_now % (markup, gobject.markup_escape_text(self.event.title.strip() ))
			else:
				rowString = self.row_string_template % (markup, gobject.markup_escape_text(self.event.title.strip() ))
		return rowString
	def getDurationMarkup(self):
		mpart=""
		hpart=""
		dpart=""
		ppart=""
		td = self.event.duration
		hours,minutes =  map(int,td.__str__()[-7:-3].split(':'))
		if(hours != 0):
			hpart = "%d%s" % (hours,HOUR)
			if(minutes != 0):
				mpart = "%d%s" % (minutes,MINUTE)		
		else:
			if(minutes != 0):
				mpart = "%d%s" % (minutes,MINUTE)
		if(td.days != 0):
			if(td.days == 1):
				dpart = "%d %s " % (td.days,DAY)
			else:
				dpart = "%d %s " % (td.days,DAYS)
			return ("<small>%s%s%s</small>" %(dpart,hpart,mpart)).strip()
		return ("<small>%s (%s%s%s)</small>" %(self.getHourMinuteMarkup(self.event.end_time),dpart,hpart,mpart)).strip()
		
	def getHourMinuteMarkup(self,dt):
		return dt.strftime(TIME_FMT)
	def getHourMinuteMarkup_ampm(self,dt):
		return dt.strftime(TIME_FMT).replace(':00','').strip()
	def on_enter_cb(self,widget = None,event = None):
		
		self.toggle_time_ingo_vis(True)
		t = underlineRe.sub('',self.name_label.get_label())
		self.name_label.set_markup("<u>%s</u>" % t)

		self.nameEvtBox.window.set_cursor(PointerCursor)
			
	def on_leave_cb(self,widget = None,event = None):
		self.toggle_time_ingo_vis(False)
		t = underlineRe.sub('',self.name_label.get_label())
		self.name_label.set_markup(t)
		self.nameEvtBox.window.set_cursor(None)

		pass
	def on_click_cb(self, widget,event):
		#print "on_click_cb"
		if (event.button == 1):
			if(self.details.get_property('visible')):
				self.details.hide()
				self.qdet.show()
			else:
				self.add_detail_view()
				self.details.show()
				self.qdet.hide()
			self.toggle_time_ingo_vis()
		return False

	def details_box_size_allocate(self,widget,rect):
		top,bottom,left,right = widget.get_padding()
		w = rect.width - left - right - 5
		for l in widget.get_children():
			l.set_size_request(w,-1)
		return False
		
	def toggle_time_ingo_vis(self,mouse_over = False):
		if(self.event.is_today() or self.details.get_property('visible')):
			self.time_info.show()
			return
		if(mouse_over):
			self.time_info.show()
		else:
			self.time_info.hide()
	def filter(self,filter):
		found = False
		if filter.text == "":
			return True
		if filter.filter & FilterType.FilterName:
			if filter.text in self.event.title.lower():
				found = True
		if not found and filter.filter & FilterType.FilterComment:
			if(filter.text in self.event.comment.lower()):
				found = True
		if not found and filter.filter & FilterType.FilterCalendar:
			if(filter.text in self.event.cal_name.lower()):
				found = True	
		if not found and filter.filter & FilterType.FilterPlace:
			if(filter.text in self.event.place.lower()):
				found = True
		if not found and filter.filter & FilterType.FilterTime:
			if(	filter.text in self.start_time.lower()
				or filter.text in self.day4filter):
				found = True
		return found
if(locale.nl_langinfo(locale.T_FMT_AMPM) != ''):
	EventWidget.getHourMinuteMarkup = EventWidget.getHourMinuteMarkup_ampm
